#ifndef __SERVICE__
#define __SERVICE__

#include "base.h"
#include "message.h"
#include "time_mgr.h"
#include "stream_reader.h"

class Thread;
class Service;

typedef void(*MsgHandle)(Service& self, StreamReader& params);
typedef std::map<std::string, MsgHandle> MsgHandleMap;

class Service {
	friend class ServiceMgr;
public:
	Service() : state_(SERVICE_STATE_INIT),
		processInterval_(SERVICE_DEFAULT_INTERVAL),
		nextProcessTime_(0) {}

	virtual ~Service() {}

public:
	virtual void onAllocThread(Thread* thread) {}

	virtual void onRemoveFromThread() {}

	virtual void processBase() {};

	void process();

	virtual bool autoStart() {
		return false;
	}

	inline bool isExit() {
		return state_ == SERVICE_STATE_EXIT;
	}
public:
	inline void setHandle(const Guid64& handle) {
		handle_ = handle;
	}

	inline const Guid64& getHandle() const {
		return handle_;
	}

	inline void setName(const std::string& name) {
		name_ = name;
	}

	inline const std::string& getName() const {
		return name_;
	}

	inline void SetProcessInterval(uint64 interval) {
		shengine_assert(interval > 0);
		processInterval_ = interval;
	}

protected:
	virtual void start() {}

	virtual void stop() { if (finalsave()) stopok(); }

	void stopok() { state_ = SERVICE_STATE_EXIT; }

	virtual bool finalsave() { return true; }

	virtual void kickme() {
		if (state_ != SERVICE_STATE_TOEXIT
			&& state_ != SERVICE_STATE_EXITING
			&& state_ != SERVICE_STATE_EXIT) {
			state_ = SERVICE_STATE_TOEXIT;
		}
		else {
			shengine_assert(0);
		}
	};

	virtual void processFrame() {};

	virtual bool handleMessage(uint8 funcType, const char* funcName, StreamReader& params);

	inline void _registerMsgHandle(const std::string& msgName, MsgHandle msgHandle) {
		msgHandleMap_.insert(std::make_pair(msgName, msgHandle));
	}

#define registerMsgHandle(MSGHANDLE) _registerMsgHandle(#MSGHANDLE, (MsgHandle)MSGHANDLE);

private:
	void _handleMessage(Message* msg);

	void checkState();

	bool checkProcessFrame();

	void processMsg();

	inline MessageQueue* getMsgQueue() {
		return &msgQueue_;
	}

protected:
	Guid64 handle_;
	std::string name_;
	int32 state_;
	uint64 processInterval_;
	uint64 nextProcessTime_;
	MessageQueue msgQueue_;
	MsgHandleMap msgHandleMap_;
};

#endif
